package com.example.demo.utils.bean;


import com.example.demo.utils.reflection.ReflectionUtils;
import com.example.demo.utils.common.StringUtils;
import org.springframework.cglib.beans.BeanMap;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * javabean处理通用类
 */
public class BeanUtils extends org.springframework.beans.BeanUtils {
	/**
	 * 获取指定bean对象内的属性(含get或is方法的属性)名称
	 *
	 * @param bean 制定bean对象
	 * @return
	 */
	public static List<String> getBeanFieldNames(Object bean) {
		Class<?> clazz = bean.getClass();
		return ReflectionUtils.findBeanNames(clazz);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean      指定对象
	 * @param fieldName 属性字符串（以.来间隔各个属性名称）
	 * @return
	 */
	public static Object getValue(Object bean, String fieldName) {
		String[] tokens = fieldName.split("\\.");
		return getValue(bean, tokens);
	}

	/**
	 * 判断指定属性(含get或is方法的属性)在指定对象中是否存在并且不为空
	 *
	 * @param bean      指定对象
	 * @param fieldName 指定属性字符串（以.分割属性名称）
	 * @return
	 */
	public static boolean contains(Object bean, String fieldName) {
		String[] fieldNames = fieldName.split("\\.");
		return contains(bean, fieldNames);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值（遍历从第一位开始）
	 *
	 * @param bean       指定对象
	 * @param fieldNames 指定属性列表（取最后一个）
	 * @return
	 */
	public static Object getValue(Object bean, String[] fieldNames) {
		return getValue(bean, fieldNames, 0);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean       指定对象
	 * @param fieldNames 指定属性列表（取最后一个）
	 * @param offset     遍历起始位置
	 * @return
	 */
	public static Object getValue(Object bean, String[] fieldNames, int offset) {
		Object fieldValue = bean;
		if (fieldValue == null) {
			return null;
		}
		for (int i = offset; i < fieldNames.length; i++) {
			fieldValue = ReflectionUtils.invokeGetMethod(fieldValue, fieldNames[i]);
			if (fieldValue == null) {
				break;
			}
		}
		return fieldValue;
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, Object value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, boolean value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, byte value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, short value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, int value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, long value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, char value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, float value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 获取指定属性(含get或is方法的属性)在指定对象中的值
	 *
	 * @param bean 指定对象
	 * @return
	 */
	public static void setValue(Object bean, String fieldName, double value) {
		ReflectionUtils.invokeSetMethod(bean, fieldName, value);
	}

	/**
	 * 判断指定属性在指定对象中是否存在get或is方法并且值不为空
	 *
	 * @param object 指定对象
	 * @param tokens 指定属性数组
	 * @return
	 */
	public static boolean contains(Object object, String[] tokens) {
		boolean is = true;
		Object fieldValue = object;
		for (int i = 0; i < tokens.length; i++) {
			if (!ReflectionUtils.hasGetMethod(object, tokens[i])) {
				is = false;
				break;
			}

			fieldValue = ReflectionUtils.invokeGetMethod(fieldValue, tokens[i]);
			if (fieldValue == null) {
				break;
			}
		}
		return is;
	}

	public static <T> T copy(T source) {
		T dest = (T) ReflectionUtils.newInstance(source.getClass());
		BeanUtils.copyProperties(source, dest);
		return dest;
	}


	public static <T> Map<String, Object> beanToMap(T bean) {
		Map<String, Object> map = new HashMap<>();
		if (bean != null) {
			BeanMap beanMap = BeanMap.create(bean);
			for (Object key : beanMap.keySet()) {
				map.put(key + "", beanMap.get(key));
			}
		}
		return map;
	}

	public static <T> Map<String, String> beanToStringMap(T bean) {
		Map<String, String> map = new HashMap<>();
		if (bean != null) {
			BeanMap beanMap = BeanMap.create(bean);
			for (Object key : beanMap.keySet()) {
				map.put(key + "", StringUtils.makeToString(beanMap.get(key), ""));
			}
		}
		return map;
	}

	public static <T> T mapToBean(Map<String, Object> map, T bean) {
		BeanMap beanMap = BeanMap.create(bean);
		beanMap.putAll(map);
		return bean;
	}

	public static <T> T mapToBeanNew(Map<Object, Object> map, T bean) {
		BeanMap beanMap = BeanMap.create(bean);
		beanMap.putAll(map);
		return bean;
	}
}
